package com.eastdigit.system.service;

import com.eastdigit.servlet.ReqBean;
import com.eastdigit.system.model.TreeEntity;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public abstract class BaseTreeService extends BaseService {

    /**
     * 保存树节点，必须按照层级和每层的顺序排序
     * 
     * @param all
     * @param reqBean
     * @param <T>
     * @return
     */
    public <T extends TreeEntity> List<T> saveTreeOrder(List<T> all, ReqBean reqBean) {

        List<T> modifys = new ArrayList<T>();// 需要修改的节点

        if (all == null || all.size() < 1) {
            return modifys;
        }

        String sourcestr = reqBean.getInfo("source");
        String targetstr = reqBean.getInfo("target");

        if (sourcestr.equals(targetstr)) {
            return modifys;
        }

        Map<String, T> map = new HashMap<String, T>();
        for (T tree : all) {
            map.put(tree.getId(), tree); // map结构 所有菜单
        }

        T virtual = null;
        try {
            virtual = (T) all.get(0).getClass().newInstance();// id=null;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        for (T tree : all) {// 组成一个树
            T parent = map.get(tree.getParentId());
            if (parent != null) {
                tree.setParent(parent);
            } else {
                virtual.addChild(tree); // virtual:一棵树
            }
        }
        T source = map.get(sourcestr);
        T target = map.get(targetstr);

        String point = reqBean.getInfo("point");// append、top、bottom

        // 修改原来的兄弟节点
        T sourceParent = map.get(source.getParentId());
        if (sourceParent == null) {
            sourceParent = virtual;
        }
        sourceParent.removeChild(source);
        modifys.addAll(updateChildrenOrder(sourceParent));

        // 修改目标节点的兄弟节点
        if ("append".equals(point)) {// 移动到内部
            target.addChild(source);
            modifys.addAll(updateChildrenOrder(target));
        } else {
            T parent = map.get(target.getParentId());
            if (parent == null) {
                parent = virtual;
            }
            int targetOrder = target.getOrder() == 0 ? 0 : target.getOrder() - 1;
            targetOrder = "top".equals(point) ? targetOrder : targetOrder + 1;

            /*
             * if("bottom".equals(point)){//向下移动 //+
             * if(target.getChildren()!=null&&target.getChildren().size()>0){
             * //+ target.getChildren().add(0, source); //+
             * modifys.addAll(updateChildrenOrder(target)); //+ return modifys;
             * //+ } //+ }
             */

            parent.getChildren().add(targetOrder, source);
            modifys.addAll(updateChildrenOrder(parent));
        }
        return modifys;
    }

    /**
     * 递归修改层级和排序
     * 
     * @param tree
     * @param <T>
     * @return
     */
    private <T extends TreeEntity> List<T> updateChildrenOrder(T tree) {
        List<T> modifys = new ArrayList<T>();// 需要修改的节点
        List<TreeEntity> list = tree.getChildren();
        for (int i = 0; i < list.size(); i++) {
            T t = (T) list.get(i);
            if (t.getParentId() != tree.getId() || t.getOrder() != (i + 1)) {
                t.setParentId(tree.getId());
                t.setOrder(i + 1);
                modifys.add(t);
                modifys.addAll(updateChildrenOrder(t));
            }
        }
        return modifys;
    }

    /**
     * easyui下拉树
     * 
     * @param list
     * @param <T>
     * @return
     */
    public <T extends TreeEntity> JSONArray getComboTree(List<T> list) {
        List<ComboTree> nodeList = new ArrayList<ComboTree>();
        Map<String, ComboTree> map = new HashMap<String, ComboTree>();
        if (list != null && list.size() > 0) {
            for (TreeEntity tree : list) {
                ComboTree combo = new ComboTree();
                combo.setId(tree.getId());
                combo.setText(tree.getName());
                map.put(combo.getId(), combo);

                ComboTree parent = map.get(tree.getParentId());
                if (parent != null) {
                    combo.setParent(parent);
                } else {
                    nodeList.add(combo);
                }
            }
        }
        return JSONArray.fromObject(nodeList);
    }

    /**
     * 返回节点嵌套数组 +++++
     * 
     * @param idName
     * @param parentIdName
     * @param jsonArray
     * @return
     */
    protected static JSONArray queryTreeGrid(String idName, String parentIdName, JSONArray jsonArray) {
        Map<String, JSONObject> map = new HashMap<String, JSONObject>();
        List<JSONObject> deletes = new ArrayList<JSONObject>();
        if (jsonArray != null) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject json = jsonArray.getJSONObject(i);
                String parentId = json.getString(parentIdName);
                JSONObject parent = map.get(parentId);
                if (parent == null && !parentId.equals("0")) {// x 是根节点
                    for (int j = 0; j < jsonArray.size(); j++) {
                        JSONObject exitParent = jsonArray.getJSONObject(j);
                        if (exitParent.getString(idName).equals(parentId)) {
                            parent = exitParent;
                        }
                    }
                }
                if (parent != null) {// 存在父节点
                    JSONArray children = parent.optJSONArray("children");
                    if (children == null) {
                        parent.put("children", new JSONArray());
                        children = parent.getJSONArray("children");// bug，必须这样，不是一个对象
                    }
                    deletes.add(json);
                    children.add(json);
                    json = children.getJSONObject(children.size() - 1);// 重新获取
                }
                map.put(json.getString(idName), json);
            }
            for (JSONObject jsonObject : deletes) {
                jsonArray.remove(jsonObject);
            }
        }
        return jsonArray;
    }

    /**
     * 平铺
     * 
     * @param idName
     * @param parentIdName
     * @param jsonArray
     * @return
     */
    public static JSONArray queryTreeGridFlat(String idName, String parentIdName, JSONArray jsonArray) {
        jsonArray = queryTreeGrid(idName, parentIdName, jsonArray);
        JSONArray array = new JSONArray();
        for (int i = 0; i < jsonArray.size(); i++) {
            addTreeGrid(array, jsonArray.getJSONObject(i));
        }
        return array;
    }

    private static void addTreeGrid(JSONArray array, JSONObject jsonObject) {
        JSONArray children = jsonObject.optJSONArray("children");
        if (children != null) {
            jsonObject.remove("children");
        }
        array.add(jsonObject);
        if (children != null) {
            for (int i = 0; i < children.size(); i++) {
                addTreeGrid(array, children.getJSONObject(i));
            }
        }
    }

    public class ComboTree {
        public String id;
        public String text;
        private List<ComboTree> children = new ArrayList<ComboTree>();

        public List<ComboTree> getChildren() {
            return children;
        }

        public void addChild(ComboTree tree) {
            children.add(tree);
        }

        public void setParent(ComboTree tree) {
            tree.addChild(this);
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

    }
}
